home *** CD-ROM | disk | FTP | other *** search
/ FishMarket 1.0 / FishMarket v1.0.iso / fishies / 076-100 / disk_077 / misc / cmp.d next >
Text File  |  1992-05-06  |  15KB  |  780 lines

  1. #include:util.g
  2. #include:crt.g
  3.  
  4. int
  5.     SCANRANGE = 20,
  6.     BINARYBLOCKCOUNT = 8,
  7.     BUFFERSIZE = 8 * 1024,
  8.     LINECOUNT = 25,
  9.     LINEBUFFERSIZE = 4 * 1024;
  10.  
  11. channel input binary ChB1, ChB2;
  12. channel input text ChT1, ChT2;
  13. file(BUFFERSIZE) File1, File2;
  14. channel output text CRT;
  15.  
  16. uint
  17.     LineNext1,
  18.     LineNext2,
  19.     LineCount,
  20.     FullLineLength,
  21.     HalfLineLength;
  22.  
  23. uint
  24.     LineNumber1,
  25.     LineNumber2;
  26.  
  27. ushort LinesPerScreen;
  28.  
  29. bool
  30.     TextMode,
  31.     Visual,
  32.     Wrappable,
  33.     Eof1,
  34.     Eof2;
  35.  
  36. [LINECOUNT] uint
  37.     Line1,
  38.     Line2;
  39.  
  40. [LINEBUFFERSIZE] char
  41.     LineBuffer1,
  42.     LineBuffer2;
  43.  
  44. proc closeBoth()void:
  45.  
  46.     if TextMode then
  47.     close(ChT1);
  48.     close(ChT2);
  49.     else
  50.     close(ChB1);
  51.     close(ChB2);
  52.     fi;
  53. corp;
  54.  
  55. proc doAbort()void:
  56.  
  57.     closeBoth();
  58.     CRT_Abort();
  59. corp;
  60.  
  61. proc checkWait()void:
  62.     char ch;
  63.  
  64.     if LineCount = LinesPerScreen - 1 then
  65.     if TextMode then
  66.         write(CRT; '\t', ChT1, " line ", LineNumber1, " \t\t\t");
  67.     else
  68.         write(CRT; '\t', ChB1, "  \t\t\t\t");
  69.     fi;
  70.     if TextMode then
  71.         write(CRT; ChT2, " line ", LineNumber2, '\r');
  72.     else
  73.         write(CRT; ChB2, '\r');
  74.     fi;
  75.     ch := CRT_ReadChar();
  76.     CRT_ClearLine(LinesPerScreen - 1);
  77.     if ch = '\(0x03)' then
  78.         doAbort();
  79.     elif ch = '\r' or ch = '\n' then
  80.         LineCount := LineCount - 1;
  81.         CRT_Scroll();
  82.         CRT_ClearLine(LinesPerScreen - 2);
  83.     else
  84.         LineCount := 0;
  85.         CRT_ClearScreen();
  86.     fi;
  87.     fi;
  88.     LineCount := LineCount + 1;
  89. corp;
  90.  
  91. proc nl()void:
  92.  
  93.     write(CRT; "\r\n");
  94.     checkWait();
  95. corp;
  96.  
  97. proc removeLine1()void:
  98.     uint pos, i, p;
  99.  
  100.     LineNumber1 := LineNumber1 + 1;
  101.     pos := Line1[1];
  102.     p := 0;
  103.     i := Line1[LineNext1];
  104.     while pos ~= i do
  105.     LineBuffer1[p] := LineBuffer1[pos];
  106.     p := p + 1;
  107.     pos := pos + 1;
  108.     od;
  109.     LineNext1 := LineNext1 - 1;
  110.     pos := Line1[1];
  111.     for i from 0 upto LineNext1 do
  112.     Line1[i] := Line1[i + 1] - pos;
  113.     od;
  114. corp;
  115.  
  116. proc removeLine2()void:
  117.     uint pos, i, p;
  118.  
  119.     LineNumber2 := LineNumber2 + 1;
  120.     pos := Line2[1];
  121.     p := 0;
  122.     i := Line2[LineNext2];
  123.     while pos ~= i do
  124.     LineBuffer2[p] := LineBuffer2[pos];
  125.     p := p + 1;
  126.     pos := pos + 1;
  127.     od;
  128.     LineNext2 := LineNext2 - 1;
  129.     pos := Line2[1];
  130.     for i from 0 upto LineNext2 do
  131.     Line2[i] := Line2[i + 1] - pos;
  132.     od;
  133. corp;
  134.  
  135. proc flush1()void:
  136.     uint pos, len, i;
  137.  
  138.     pos := 0;
  139.     len := Line1[1] - 1;
  140.     while pos ~= len do
  141.     i := 0;
  142.     CRT_EnterHighLight();
  143.     while i ~= HalfLineLength and pos ~= len do
  144.         if LineBuffer1[pos] = '\t' then
  145.         LineBuffer1[pos] := '\(0x80)' + ((i + 8) / 8 * 8 - i);
  146.         fi;
  147.         if LineBuffer1[pos] >= '\(0x80)' then
  148.         while LineBuffer1[pos] ~= '\(0x80)' and
  149.             i ~= HalfLineLength do
  150.             write(CRT; ' ');
  151.             i := i + 1;
  152.             LineBuffer1[pos] := LineBuffer1[pos] - 1;
  153.         od;
  154.         if LineBuffer1[pos] = '\(0x80)' then
  155.             pos := pos + 1;
  156.         fi;
  157.         else
  158.         write(CRT; LineBuffer1[pos]);
  159.         i := i + 1;
  160.         pos := pos + 1;
  161.         fi;
  162.     od;
  163.     while i ~= HalfLineLength do
  164.         write(CRT; ' ');
  165.         i := i + 1;
  166.     od;
  167.     CRT_ExitHighLight();
  168.     write(CRT; '|');
  169.     nl();
  170.     od;
  171.     removeLine1();
  172. corp;
  173.  
  174. proc flush2()void:
  175.     uint pos, len, i;
  176.  
  177.     pos := 0;
  178.     len := Line2[1] - 1;
  179.     while pos ~= len do
  180.     for i from 0 upto HalfLineLength - 1 do
  181.         write(CRT; ' ');
  182.     od;
  183.     write(CRT; '|');
  184.     i := 0;
  185.     CRT_EnterHighLight();
  186.     while i ~= HalfLineLength and pos ~= len do
  187.         if LineBuffer2[pos] = '\t' then
  188.         LineBuffer2[pos] := '\(0x80)' + ((i + 8) / 8 * 8 - i);
  189.         fi;
  190.         if LineBuffer2[pos] >= '\(0x80)' then
  191.         while LineBuffer2[pos] ~= '\(0x80)' and
  192.             i ~= HalfLineLength do
  193.             write(CRT; ' ');
  194.             i := i + 1;
  195.             LineBuffer2[pos] := LineBuffer2[pos] - 1;
  196.         od;
  197.         if LineBuffer2[pos] = '\(0x80)' then
  198.             pos := pos + 1;
  199.         fi;
  200.         else
  201.         write(CRT; LineBuffer2[pos]);
  202.         i := i + 1;
  203.         pos := pos + 1;
  204.         fi;
  205.     od;
  206.     CRT_ExitHighLight();
  207.     if Wrappable and i = HalfLineLength then
  208.         checkWait();
  209.     else
  210.         nl();
  211.     fi;
  212.     od;
  213.     removeLine2();
  214. corp;
  215.  
  216. proc flushBoth()void:
  217.     uint pos1, pos2, len1, len2, i;
  218.  
  219.     pos1 := 0;
  220.     pos2 := 0;
  221.     len1 := Line1[1] - 1;
  222.     len2 := Line2[1] - 1;
  223.     if len1 = 0 and len2 = 0 then
  224.     /* need this, since the main while wouldn't do anything */
  225.     for i from 0 upto HalfLineLength - 1 do
  226.         write(CRT; ' ');
  227.     od;
  228.     write(CRT; '|');
  229.     nl();
  230.     fi;
  231.     while pos1 ~= len1 or pos2 ~= len2 do
  232.     i := 0;
  233.     while i ~= HalfLineLength and pos1 ~= len1 do
  234.         if LineBuffer1[pos1] = '\t' then
  235.         LineBuffer1[pos1] := '\(0x80)' + ((i + 8) / 8 * 8 - i);
  236.         fi;
  237.         if LineBuffer1[pos1] >= '\(0x80)' then
  238.         while LineBuffer1[pos1] ~= '\(0x80)' and
  239.             i ~= HalfLineLength do
  240.             write(CRT; ' ');
  241.             i := i + 1;
  242.             LineBuffer1[pos1] := LineBuffer1[pos1] - 1;
  243.         od;
  244.         if LineBuffer1[pos1] = '\(0x80)' then
  245.             pos1 := pos1 + 1;
  246.         fi;
  247.         else
  248.         write(CRT; LineBuffer1[pos1]);
  249.         i := i + 1;
  250.         pos1 := pos1 + 1;
  251.         fi;
  252.     od;
  253.     while i ~= HalfLineLength do
  254.         write(CRT; ' ');
  255.         i := i + 1;
  256.     od;
  257.     write(CRT; '|');
  258.     i := 0;
  259.     while i ~= HalfLineLength and pos2 ~= len2 do
  260.         if LineBuffer2[pos2] = '\t' then
  261.         LineBuffer2[pos2] := '\(0x80)' + ((i + 8) / 8 * 8 - i);
  262.         fi;
  263.         if LineBuffer2[pos2] >= '\(0x80)' then
  264.         while LineBuffer2[pos2] ~= '\(0x80)' and
  265.             i ~= HalfLineLength do
  266.             write(CRT; ' ');
  267.             i := i + 1;
  268.             LineBuffer2[pos2] := LineBuffer2[pos2] - 1;
  269.         od;
  270.         if LineBuffer2[pos2] = '\(0x80)' then
  271.             pos2 := pos2 + 1;
  272.         fi;
  273.         else
  274.         write(CRT; LineBuffer2[pos2]);
  275.         i := i + 1;
  276.         pos2 := pos2 + 1;
  277.         fi;
  278.     od;
  279.     if Wrappable and i = HalfLineLength then
  280.         checkWait();
  281.     else
  282.         nl();
  283.     fi;
  284.     od;
  285.     removeLine1();
  286.     removeLine2();
  287. corp;
  288.  
  289. proc getLine1()void:
  290.     uint pos;
  291.     char ch;
  292.     bool first;
  293.  
  294.     pos := Line1[LineNext1];
  295.     first := true;
  296.     while
  297.     if first then
  298.         if not read(ChT1; ch) then
  299.         first := false;
  300.         fi;
  301.         true
  302.     else
  303.         false
  304.     fi
  305.     do
  306.     if pos = LINEBUFFERSIZE then
  307.         if LineNext1 = 0 then
  308.         write(ChT1, ": input line too long.\r\n");
  309.         doAbort();
  310.         fi;
  311.         Line1[LineNext1 + 1] := pos;
  312.         if CharsEqual(&LineBuffer1[Line1[0]],
  313.               &LineBuffer2[Line2[0]]) then
  314.         flushBoth();
  315.         else
  316.         flush1();
  317.         flush2();
  318.         fi;
  319.     fi;
  320.     LineBuffer1[pos] := ch;
  321.     pos := pos + 1;
  322.     od;
  323.     if pos ~= Line1[LineNext1] then
  324.     LineBuffer1[pos - 1] := '\e';
  325.     Line1[LineNext1 + 1] := pos;
  326.     LineNext1 := LineNext1 + 1;
  327.     fi;
  328.     if ioerror(ChT1) = CH_EOF or not readln(ChT1;) then
  329.     Eof1 := true;
  330.     fi;
  331. corp;
  332.  
  333. proc getLine2()void:
  334.     uint pos;
  335.     char ch;
  336.     bool first;
  337.  
  338.     pos := Line2[LineNext2];
  339.     first := true;
  340.     while
  341.     if first then
  342.         if not read(ChT2; ch) then
  343.         first := false;
  344.         fi;
  345.         true
  346.     else
  347.         false
  348.     fi
  349.     do
  350.     if pos = LINEBUFFERSIZE then
  351.         if LineNext2 = 0 then
  352.         write(ChT2, ": input line too long.\r\n");
  353.         doAbort();
  354.         fi;
  355.         Line2[LineNext2 + 1] := pos;
  356.         if CharsEqual(&LineBuffer1[Line1[0]],
  357.               &LineBuffer2[Line2[0]]) then
  358.         flushBoth();
  359.         else
  360.         flush1();
  361.         flush2();
  362.         fi;
  363.     fi;
  364.     LineBuffer2[pos] := ch;
  365.     pos := pos + 1;
  366.     od;
  367.     if pos ~= Line2[LineNext2] then
  368.     LineBuffer2[pos - 1] := '\e';
  369.     Line2[LineNext2 + 1] := pos;
  370.     LineNext2 := LineNext2 + 1;
  371.     fi;
  372.     if ioerror(ChT2) = CH_EOF or not readln(ChT2;) then
  373.     Eof2 := true;
  374.     fi;
  375. corp;
  376.  
  377. proc visualTextCompare()void:
  378.     uint i, j;
  379.  
  380.     CRT_ClearScreen();
  381.     Eof1 := false;
  382.     Eof2 := false;
  383.     LineNext1 := 0;
  384.     LineNext2 := 0;
  385.     Line1[0] := 0;
  386.     Line2[0] := 0;
  387.     LineNumber1 := 1;
  388.     LineNumber2 := 1;
  389.     while
  390.     if LineNext1 = 0 then
  391.         getLine1();
  392.     fi;
  393.     if LineNext2 = 0 then
  394.         getLine2();
  395.     fi;
  396.     not Eof1 or not Eof2
  397.     do
  398.     if CharsEqual(&LineBuffer1[Line1[0]],
  399.               &LineBuffer2[Line2[0]]) then
  400.         flushBoth();
  401.     else
  402.         i := 1;
  403.         while
  404.         if Eof1 and Eof2 then
  405.             false
  406.         else
  407.             if i = LineNext1 and not Eof1 then
  408.             getLine1();
  409.             fi;
  410.             if i = LineNext2 and not Eof2 then
  411.             getLine2();
  412.             fi;
  413.             i ~= SCANRANGE and (not Eof1 or not Eof2) and
  414.             if Eof2 then
  415.                 true
  416.             else
  417.                 j := 0;
  418.                 while j <= i and
  419.                 not CharsEqual(&LineBuffer1[Line1[j]],
  420.                            &LineBuffer2[Line2[i]])
  421.                 do
  422.                 j := j + 1;
  423.                 od;
  424.                 j > i
  425.             fi and
  426.             if Eof1 then
  427.                 true
  428.             else
  429.                 j := 0;
  430.                 while j <= i and
  431.                 not CharsEqual(&LineBuffer1[Line1[i]],
  432.                            &LineBuffer2[Line2[j]])
  433.                 do
  434.                 j := j + 1;
  435.                 od;
  436.                 j > i
  437.             fi
  438.  
  439.             fi
  440.         do
  441.         i := i + 1;
  442.         od;
  443.         if Eof1 and Eof2 then
  444.         elif not Eof2 and CharsEqual(&LineBuffer1[Line1[j]],
  445.                      &LineBuffer2[Line2[i]]) then
  446.         while i ~= 0 do
  447.             flush2();
  448.             i := i - 1;
  449.         od;
  450.         elif not Eof1 and CharsEqual(&LineBuffer1[Line1[i]],
  451.                      &LineBuffer2[Line2[j]]) then
  452.         while i ~= 0 do
  453.             flush1();
  454.             i := i - 1;
  455.         od;
  456.         else
  457.         if not Eof1 then
  458.             flush1();
  459.         fi;
  460.         if not Eof2 then
  461.             flush2();
  462.         fi;
  463.         fi;
  464.     fi;
  465.     od;
  466.     while LineNext1 ~= 0 do
  467.     flush1();
  468.     od;
  469.     while not Eof1 do
  470.     getLine1();
  471.     while LineNext1 ~= 0 do
  472.         flush1();
  473.     od;
  474.     od;
  475.     while LineNext2 ~= 0 do
  476.     flush2();
  477.     od;
  478.     while not Eof2 do
  479.     getLine2();
  480.     while LineNext2 ~= 0 do
  481.         flush2();
  482.     od;
  483.     od;
  484.     while LineCount ~= 1 do
  485.     nl();
  486.     od;
  487. corp;
  488.  
  489. proc visualBinaryCompare()void:
  490.     [BINARYBLOCKCOUNT] byte block1, block2;
  491.     uint pos;
  492.     ushort i;
  493.     byte b1, b2;
  494.     bool different;
  495.  
  496.     CRT_ClearScreen();
  497.     pos := 0;
  498.     while
  499.     for i from 0 upto BINARYBLOCKCOUNT - 1 do
  500.         block1[i] := 1;
  501.         block2[i] := 2;
  502.     od;
  503.     read(ChB1; block1) and read(ChB2; block2)
  504.     do
  505.     write(CRT; pos : x : -4);
  506.     for i from 0 upto BINARYBLOCKCOUNT - 1 do
  507.         b1 := block1[i];
  508.         b2 := block2[i];
  509.         write(CRT; if i = 0 then ':' else ' ' fi);
  510.         if b1 ~= b2 then
  511.         CRT_EnterHighLight();
  512.         fi;
  513.         write(CRT; b1 : x : -2);
  514.         if b1 ~= b2 then
  515.         CRT_ExitHighLight();
  516.         fi;
  517.     od;
  518.     write(CRT; '*');
  519.     different := false;
  520.     for i from 0 upto BINARYBLOCKCOUNT - 1 do
  521.         b1 := block1[i];
  522.         b2 := block2[i];
  523.         if b1 ~= b2 then
  524.         if not different then
  525.             different := true;
  526.             CRT_EnterHighLight();
  527.         fi;
  528.         else
  529.         if different then
  530.             different := false;
  531.             CRT_ExitHighLight();
  532.         fi;
  533.         fi;
  534.         write(CRT;
  535.         if b1 >= 0x20 and b1 <= 0x7f then
  536.             b1 + '\e'
  537.         else
  538.             '.'
  539.         fi);
  540.     od;
  541.     if different then
  542.         CRT_ExitHighLight();
  543.     fi;
  544.     write(CRT; "*|", pos : x : -4);
  545.     for i from 0 upto BINARYBLOCKCOUNT - 1 do
  546.         b1 := block1[i];
  547.         b2 := block2[i];
  548.         write(CRT; if i = 0 then ':' else ' ' fi);
  549.         if b1 ~= b2 then
  550.         CRT_EnterHighLight();
  551.         fi;
  552.         write(CRT; b2 : x : -2);
  553.         if b1 ~= b2 then
  554.         CRT_ExitHighLight();
  555.         fi;
  556.     od;
  557.     write(CRT; '*');
  558.     different := false;
  559.     for i from 0 upto BINARYBLOCKCOUNT - 1 do
  560.         b1 := block1[i];
  561.         b2 := block2[i];
  562.         if b1 ~= b2 then
  563.         if not different then
  564.             different := true;
  565.             CRT_EnterHighLight();
  566.         fi;
  567.         else
  568.         if different then
  569.             different := false;
  570.             CRT_ExitHighLight();
  571.         fi;
  572.         fi;
  573.         write(CRT;
  574.         if b2 >= 0x20 and b2 <= 0x7f then
  575.             b2 + '\e'
  576.         else
  577.             '.'
  578.         fi);
  579.     od;
  580.     if different then
  581.         CRT_ExitHighLight();
  582.     fi;
  583.     write(CRT; '*');
  584.     nl();
  585.     pos := pos + BINARYBLOCKCOUNT;
  586.     od;
  587.     while LineCount ~= 1 do
  588.     nl();
  589.     od;
  590. corp;
  591.  
  592. proc showChar(char c)void:
  593.  
  594.     write('\'', if c < ' ' or c > '~' then '.' else c fi, "' (hex ",
  595.         c - '\e' : x : -2, ')');
  596. corp;
  597.  
  598. proc textCompare()void:
  599.     char c1, c2;
  600.     uint line, col;
  601.     bool eof1, eof2;
  602.  
  603.     line := 1;
  604.     col := 1;
  605.     while
  606.     while if read(ChT1; c1) then 1 else 0 fi &
  607.         if read(ChT2; c2) then 1 else 0 fi ~= 0 and c1 = c2 do
  608.         if c1 = '\t' then
  609.         col := (col + 7) & (-8) + 1;
  610.         else
  611.         col := col + 1;
  612.         fi;
  613.     od;
  614.     eof1 := ioerror(ChT1) = CH_EOF;
  615.     eof2 := ioerror(ChT2) = CH_EOF;
  616.     not eof1 and not eof2 and c1 = c2
  617.     do
  618.     readln(ChT1;);
  619.     readln(ChT2;);
  620.     line := line + 1;
  621.     col := 1;
  622.     od;
  623.     if eof1 and eof2 then
  624.     writeln("Files ", ChT1, " and ", ChT2, " are identical.")
  625.     elif eof1 then
  626.     writeln("File ", ChT2, " contains more text than file ", ChT1,'.');
  627.     elif eof2 then
  628.     writeln("File ", ChT1, " contains more text than file ", ChT2,'.');
  629.     else
  630.     write("Line ", line, ", col ", col, ", ", ChT1, " has ");
  631.     showChar(c1);
  632.     write(", but ", ChT2, " has ");
  633.     showChar(c2);
  634.     writeln('.');
  635.     fi;
  636. corp;
  637.  
  638. proc binaryCompare()void:
  639.     uint pos;
  640.     byte b1, b2;
  641.     bool eof1, eof2;
  642.  
  643.     pos := 0;
  644.     while if read(ChB1; b1) then 1 else 0 fi &
  645.         if read(ChB2; b2) then 1 else 0 fi ~= 0 and b1 = b2 do
  646.     pos := pos + 1;
  647.     od;
  648.     eof1 := ioerror(ChB1) = CH_EOF;
  649.     eof2 := ioerror(ChB2) = CH_EOF;
  650.     if eof1 and eof2 then
  651.     writeln("Files ", ChB1, " and ", ChB2, " are identical.")
  652.     elif eof1 then
  653.     writeln("File ", ChB2, " contains more data than file ", ChB1,'.');
  654.     elif eof2 then
  655.     writeln("File ", ChB1, " contains more data than file ", ChB2,'.');
  656.     else
  657.     writeln("At ", pos, " (hex ", pos : x : -4, "), ", ChB1,
  658.         " has hex ", b1 : x : -2, ", but ", ChB2,
  659.         " has hex ", b2 : x : -2, '.');
  660.     fi;
  661. corp;
  662.  
  663. proc badUsage()void:
  664.  
  665.     writeln("Use is: cmp [-?tbv] file1 file2");
  666.     exit(1);
  667. corp;
  668.  
  669. proc instructions()void:
  670.  
  671.     CRT_Initialize("Cmp V1.0", 23, 77);
  672.     CRT_Chars(
  673.     "\n\n\n"
  674.     "Cmp can compare text and binary files, either visually or using a "
  675.     "quick, non-visual mode. Flags 'b' and 't' select either binary or "
  676.     "text mode (default binary). Flag 'v' selects a visual compare, "
  677.     "quick being the default. Cmp will wait at the end of each "
  678.     "screenful. When waiting, a carriage "
  679.     "return will advance 1 line, any other key will advance 1 screen. "
  680.     "Examples:\n\n"
  681.     "    cmp fyle1.dat fyle2.dat\n"
  682.     "          - compare files as binary, using non-visual compare\n\n"
  683.     "    cmp -vt fyle1.txt fyle2.txt\n"
  684.     "          - compare text files in visual\n\n"
  685.     "    cmp -t fyle1.txt fyle2.txt\n"
  686.     "          - non-visual compare of text files"
  687.     );
  688.     CRT_Terminate();
  689.     exit(1);
  690. corp;
  691.  
  692. proc main()void:
  693.     *char par;
  694.  
  695.     par := GetPar();
  696.     TextMode := false;
  697.     Visual := false;
  698.     if par ~= nil and par* = '-' then
  699.     while
  700.         par := par + 1;
  701.         par* ~= '\e'
  702.     do
  703.         case par*
  704.         incase '?':
  705.         instructions();
  706.         incase 'v':
  707.         incase 'V':
  708.         Visual := true;
  709.         incase 't':
  710.         incase 'T':
  711.         TextMode := true;
  712.         incase 'b':
  713.         incase 'B':
  714.         TextMode := false;
  715.         default:
  716.         badUsage();
  717.         esac;
  718.     od;
  719.     par := GetPar();
  720.     fi;
  721.     if par = nil then
  722.     badUsage();
  723.     fi;
  724.     if not
  725.     if TextMode then
  726.         open(ChT1, File1, par)
  727.     else
  728.         open(ChB1, File1, par)
  729.     fi
  730.     then
  731.     writeln("Can't open file \"", par, "\".");
  732.     exit(1);
  733.     fi;
  734.     par := GetPar();
  735.     if par = nil then
  736.     badUsage();
  737.     fi;
  738.     if not
  739.     if TextMode then
  740.         open(ChT2, File2, par)
  741.     else
  742.         open(ChB2, File2, par)
  743.     fi
  744.     then
  745.     writeln("Can't open file \"", par, "\".");
  746.     if TextMode then
  747.         close(ChT1);
  748.     else
  749.         close(ChB1);
  750.     fi;
  751.     exit(1);
  752.     fi;
  753.     if Visual then
  754.     CRT_Initialize("Cmp V1.0", 0, 1);
  755.     open(CRT, CRT_PutChar);
  756.     LinesPerScreen := CRT_NLines();
  757.     LineCount := 1;
  758.     if TextMode then
  759.         FullLineLength := CRT_NCols();
  760.         HalfLineLength := (FullLineLength - 1) / 2;
  761.         Wrappable := HalfLineLength * 2 + 1 = FullLineLength;
  762.         visualTextCompare();
  763.     else
  764.         if CRT_NCols() < 78 then
  765.         writeln("Cmp: less than 78 columns - aborting.");
  766.         else
  767.         visualBinaryCompare();
  768.         fi;
  769.     fi;
  770.     CRT_Terminate();
  771.     else
  772.     if TextMode then
  773.         textCompare();
  774.     else
  775.         binaryCompare();
  776.     fi;
  777.     fi;
  778.     closeBoth();
  779. corp;
  780.